﻿// <copyright file="BoardViewer.xaml.cs" company="Marcin Wosik">
// Copyright (c) 2010 All Right Reserved
// </copyright>
// <author>Marcin Wosik</author>
// <email>mawo11@gmail.com</email>
// <date>2010-02-25</date>
// <summary></summary>
namespace GameOfLife.Controls
{
    using System;
    using System.Windows.Controls;
    using System.Windows.Input;
    using GameOfLife.GameData;
    using GameOfLife.Interfaces;

    public partial class BoardViewer : UserControl
    {
        #region Constructors

        public BoardViewer()
        {
            InitializeComponent();
        }

        #endregion Constructors

        #region Properties

        internal IBoard Board
        {
            get; private set;
        }

        internal GameSettings Data
        {
            get; set;
        }

        #endregion Properties

        #region Methods

        /// <summary>
        /// Drawing element on board
        /// </summary>
        internal virtual void DrawBoard()
        {
            if (this.Data == null || this.Data.Elements == null)
            {
                return;
            }
            for (int i = 0; i < this.Data.Elements.Count; ++i)
            {
                this.Data.Elements[i].ChangeState();
            }
        }

        /// <summary>
        /// Initialize board , creating elements
        /// </summary>
        internal void InitializeBoard()
        {
            // clear old game...
            this.Drawer.Children.Clear();

            if (this.Data == null)
            {
                return;
            }

            // build board
            this.Board = BoardFactory.CreateBoard(Data.BoardType);
            this.Board.Data = Data;
            this.Board.Initialize(Drawer);
        }

        /// <summary>
        /// Mark randomly elements on board
        /// </summary>
        internal void Random()
        {
            if (Data != null)
            {
                // calcaluting
                int maxElements = Data.Rows * Data.Columns;
                // sub 30%
                maxElements -= (int)(maxElements * 0.30);
                Random random = new Random();

                for (int i = 0; i < maxElements; ++i)
                {
                    int posX = random.Next(0, Data.Rows);
                    int posY = random.Next(0, Data.Columns);
                    MarkAsCreated(ElementBase.GetFromCord(Data.Elements, posX, posY));
                }
            }
        }

        /// <summary>
        /// Subscibe to simulation engine progress changeg
        /// </summary>
        /// <param name="engine"></param>
        internal void SubscribeToSimulationEngine(SimulationEngine engine)
        {
            if (engine != null)
            {
                engine.RedrawBoard += RedrawBoard;
            }
        }

        private void DrawerMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            if (Board != null)
            {
                IElement element = this.Board.GetElementFromCord(e.GetPosition(this));
                if (element != null)
                {
                    MarkAsCreated(element);
                }
            }
        }

        private static void MarkAsCreated(IElement element)
        {
            Random random = new Random();

            element.Current = ElementState.Created;
            switch (element.ColoringMode)
            {
                case ColorMode.Default:
                    element.Drawer.Fill = ElementBase.BlackBrush;
                    break;
                case ColorMode.Simple:
                    element.Drawer.Fill = ElementBase.GreenBrush;
                    break;
                case ColorMode.Immigration:
                    if (element.Drawer.Fill == ElementBase.RedBrush)
                    {
                        element.Drawer.Fill =ElementBase.YellowBrush;
                    }
                    else
                        if (element.Drawer.Fill == ElementBase.YellowBrush)
                        {
                            element.Drawer.Fill = ElementBase.RedBrush;
                        }
                        else
                        {
                            element.Drawer.Fill = random.Next(0, 2) == 0 ? ElementBase.RedBrush : ElementBase.YellowBrush;
                        }
                    break;
                case ColorMode.QuadLife:
                    switch (random.Next(0, 3))
                    {
                        case 0:
                            element.Drawer.Fill = ElementBase.GreenBrush;
                            break;
                        case 1:
                            element.Drawer.Fill = ElementBase.RedBrush;
                            break;
                        case 2:
                            element.Drawer.Fill = ElementBase.YellowBrush;
                            break;
                        case 3:
                            element.Drawer.Fill = ElementBase.BlueBrush;
                            break;
                    }
                    break;
            }
        }

        /// <summary>
        /// Repaint the board area
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void RedrawBoard(object sender, EventArgs e)
        {
            // check for required data for this operation
            if (this.Data == null || this.Data.Elements == null)
            {
                return;
            }

            lock (Data.Elements)
            {
                this.DrawBoard();
            }
        }

        #endregion Methods
    }
}